#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Git 代码行数统计工具 - 图形界面版本
提供简单易用的图形界面来统计 Git 仓库的代码行数
"""

import os
import sys
import threading
import tkinter as tk
from tkinter import filedialog, scrolledtext, messagebox
from tkinter import ttk
import git
from collections import defaultdict
from typing import Dict, Set, Tuple
import re
import datetime
from report_generator import HTMLReportGenerator
from file_stats_exporter import FileStatsExporter
from cache_manager import CacheManager


class GitCounterGUI:
    """Git 代码统计器 GUI"""
    
    # 前端文件扩展名
    FRONTEND_EXTENSIONS = {
        '.html', '.htm', '.css', '.scss', '.sass', '.less',
        '.js', '.jsx', '.ts', '.tsx', '.vue', '.svelte',
        '.json', '.xml', '.yaml', '.yml'
    }
    
    # 后端文件扩展名
    BACKEND_EXTENSIONS = {
        '.py', '.java', '.go', '.rb', '.php', '.c', '.cpp', '.cc',
        '.h', '.hpp', '.cs', '.rs', '.kt', '.scala', '.swift',
        '.sql', '.sh', '.bash', '.ps1'
    }
    
    # 单行注释规则
    SINGLE_LINE_COMMENT = {
        '.py': r'^\s*#',
        '.js': r'^\s*//',
        '.jsx': r'^\s*//',
        '.ts': r'^\s*//',
        '.tsx': r'^\s*//',
        '.java': r'^\s*//',
        '.c': r'^\s*//',
        '.cpp': r'^\s*//',
        '.cc': r'^\s*//',
        '.h': r'^\s*//',
        '.hpp': r'^\s*//',
        '.cs': r'^\s*//',
        '.go': r'^\s*//',
        '.php': r'^\s*(//#)',
        '.rb': r'^\s*#',
        '.sh': r'^\s*#',
        '.bash': r'^\s*#',
        '.sql': r'^\s*--',
        '.html': r'^\s*<!--',
        '.xml': r'^\s*<!--',
        '.css': r'^\s*/\*',
        '.scss': r'^\s*//',
        '.sass': r'^\s*//',
        '.less': r'^\s*//',
    }
    
    # 多行注释规则
    MULTI_LINE_COMMENT = {
        '.py': (r'^\s*"""', r'"""'),
        '.js': (r'^\s*/\*', r'\*/'),
        '.jsx': (r'^\s*/\*', r'\*/'),
        '.ts': (r'^\s*/\*', r'\*/'),
        '.tsx': (r'^\s*/\*', r'\*/'),
        '.java': (r'^\s*/\*', r'\*/'),
        '.c': (r'^\s*/\*', r'\*/'),
        '.cpp': (r'^\s*/\*', r'\*/'),
        '.cc': (r'^\s*/\*', r'\*/'),
        '.h': (r'^\s*/\*', r'\*/'),
        '.hpp': (r'^\s*/\*', r'\*/'),
        '.cs': (r'^\s*/\*', r'\*/'),
        '.go': (r'^\s*/\*', r'\*/'),
        '.php': (r'^\s*/\*', r'\*/'),
        '.css': (r'^\s*/\*', r'\*/'),
        '.scss': (r'^\s*/\*', r'\*/'),
        '.less': (r'^\s*/\*', r'\*/'),
        '.html': (r'^\s*<!--', r'-->'),
        '.xml': (r'^\s*<!--', r'-->'),
    }
    
    def __init__(self, root):
        """初始化 GUI"""
        self.root = root
        self.root.title("Git 代码行数统计工具")
        self.root.geometry("900x700")
        self.root.resizable(True, True)
        
        # 设置窗口图标（可选）
        try:
            self.root.iconbitmap('icon.ico')
        except:
            pass
        
        self.repo_path = tk.StringVar()
        self.is_analyzing = False
        
        self.create_widgets()
        
        # 统计数据
        self.stats = {
            'frontend': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
            'backend': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
            'other': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
        }
        self.file_stats = defaultdict(lambda: {'added': 0, 'deleted': 0, 'current': 0})
        
        # 当前代码量统计状态
        self.current_stats_available = False
        
        # 分账户统计数据
        self.per_user_stats = {}  # {'user1': {stats}, 'user2': {stats}, ...}
        self.user_list = []  # 用户列表
        
        # 保存仓库信息用于导出报告
        self.current_repo_path = None
        self.current_user_name = None
        self.current_user_email = None
        self.current_branch = None
        
        # 缓存管理器
        self.cache_manager = CacheManager()
        self.current_cache = None  # 当前可用的缓存
        self.current_repo = None  # 当前Git仓库对象
    
    def create_widgets(self):
        """创建 GUI 组件"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(7, weight=1)  # 结果显示区域可以伸缩
        
        # 标题
        title_label = ttk.Label(
            main_frame,
            text="Git 代码行数统计工具",
            font=('Arial', 16, 'bold')
        )
        title_label.grid(row=0, column=0, columnspan=3, pady=(0, 10))
        
        # 文件夹选择区域
        folder_frame = ttk.LabelFrame(main_frame, text="选择 Git 仓库", padding="10")
        folder_frame.grid(row=1, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(0, 10))
        folder_frame.columnconfigure(1, weight=1)
        
        ttk.Label(folder_frame, text="仓库路径:").grid(row=0, column=0, sticky=tk.W, padx=(0, 10))
        
        path_entry = ttk.Entry(folder_frame, textvariable=self.repo_path, width=50)
        path_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(0, 10))
        
        browse_btn = ttk.Button(
            folder_frame,
            text="浏览...",
            command=self.browse_folder,
            width=10
        )
        browse_btn.grid(row=0, column=2)
        
        # Git 用户信息显示
        self.git_user_info = ttk.Label(
            main_frame,
            text="当前 Git 用户：未检测",
            font=('Arial', 10),
            foreground='gray'
        )
        self.git_user_info.grid(row=2, column=0, columnspan=3, pady=(0, 10))
        
        # 用户配置区域
        user_frame = ttk.LabelFrame(main_frame, text="用户配置（可选，留空则自动检测）", padding="10")
        user_frame.grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(0, 10))
        user_frame.columnconfigure(1, weight=1)
        
        # 用户名输入
        ttk.Label(user_frame, text="用户名:").grid(row=0, column=0, sticky=tk.W, padx=(0, 10))
        self.manual_user_name = tk.StringVar()
        user_name_entry = ttk.Entry(user_frame, textvariable=self.manual_user_name, width=30)
        user_name_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(0, 10))
        
        ttk.Label(user_frame, text="（多个用户名用逗号分隔）").grid(row=0, column=2, sticky=tk.W)
        
        # 邮箱输入
        ttk.Label(user_frame, text="邮箱:").grid(row=1, column=0, sticky=tk.W, padx=(0, 10), pady=(5, 0))
        self.manual_user_email = tk.StringVar()
        user_email_entry = ttk.Entry(user_frame, textvariable=self.manual_user_email, width=30)
        user_email_entry.grid(row=1, column=1, sticky=(tk.W, tk.E), padx=(0, 10), pady=(5, 0))
        
        ttk.Label(user_frame, text="（多个邮箱用逗号分隔）").grid(row=1, column=2, sticky=tk.W, pady=(5, 0))
        
        # 统计模式选择
        ttk.Label(user_frame, text="统计模式:").grid(row=2, column=0, sticky=tk.W, padx=(0, 10), pady=(10, 0))
        self.stat_mode = tk.StringVar(value="summary")
        mode_frame = ttk.Frame(user_frame)
        mode_frame.grid(row=2, column=1, sticky=tk.W, pady=(10, 0))
        
        ttk.Radiobutton(
            mode_frame,
            text="汇总统计（快速）",
            variable=self.stat_mode,
            value="summary"
        ).pack(side=tk.LEFT, padx=(0, 20))
        
        ttk.Radiobutton(
            mode_frame,
            text="分账户统计（详细，可对比）",
            variable=self.stat_mode,
            value="detailed"
        ).pack(side=tk.LEFT)
        
        # 缓存状态显示区域
        cache_frame = ttk.LabelFrame(main_frame, text="📦 缓存状态", padding="10")
        cache_frame.grid(row=4, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(10, 0))
        cache_frame.columnconfigure(0, weight=1)
        
        # 缓存状态标签
        self.cache_status_label = ttk.Label(
            cache_frame,
            text="✗ 请先选择仓库目录",
            foreground="gray"
        )
        self.cache_status_label.grid(row=0, column=0, sticky=tk.W, pady=(0, 10))
        
        # 缓存按钮框架
        self.cache_button_frame = ttk.Frame(cache_frame)
        self.cache_button_frame.grid(row=1, column=0, sticky=tk.W)
        
        # 加载缓存按钮（初始隐藏）
        self.load_cache_btn = ttk.Button(
            self.cache_button_frame,
            text="📂 加载缓存",
            command=self.load_from_cache,
            width=15
        )
        
        # 重新统计按钮（初始隐藏）
        self.restat_btn = ttk.Button(
            self.cache_button_frame,
            text="🔄 重新统计",
            command=self.start_analysis,
            width=15
        )
        
        # 清理缓存按钮（初始显示）
        self.clear_cache_btn = ttk.Button(
            self.cache_button_frame,
            text="🗑️ 清理缓存",
            command=self.clear_all_caches,
            width=15
        )
        self.clear_cache_btn.pack(side=tk.LEFT, padx=(0, 5))
        
        # 执行按钮
        self.analyze_btn = ttk.Button(
            main_frame,
            text="开始统计",
            command=self.start_analysis,
            width=20
        )
        self.analyze_btn.grid(row=5, column=0, columnspan=3, pady=(0, 10))
        
        # 进度条
        self.progress = ttk.Progressbar(
            main_frame,
            mode='indeterminate',
            length=300
        )
        self.progress.grid(row=6, column=0, columnspan=3, pady=(0, 10))
        
        # 状态标签（隐藏的，用于代码兼容）
        self.status_label = ttk.Label(main_frame, text="")
        # 不显示，节省空间
        
        # 结果显示区域
        result_frame = ttk.LabelFrame(main_frame, text="统计结果", padding="10")
        result_frame.grid(row=7, column=0, columnspan=3, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        result_frame.columnconfigure(0, weight=1)
        result_frame.rowconfigure(0, weight=1)
        
        # 滚动文本框
        self.result_text = scrolledtext.ScrolledText(
            result_frame,
            width=80,
            height=25,
            font=('Consolas', 10),
            wrap=tk.WORD
        )
        self.result_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置文本标签（用于彩色输出）
        self.result_text.tag_config("title", foreground="#0066CC", font=('Consolas', 12, 'bold'))
        self.result_text.tag_config("header", foreground="#009900", font=('Consolas', 11, 'bold'))
        self.result_text.tag_config("info", foreground="#333333")
        self.result_text.tag_config("success", foreground="#00AA00", font=('Consolas', 10, 'bold'))
        self.result_text.tag_config("error", foreground="#CC0000", font=('Consolas', 10, 'bold'))
        self.result_text.tag_config("warning", foreground="#FF8800")
        self.result_text.tag_config("separator", foreground="#666666")
        
        # 底部按钮区域
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=8, column=0, columnspan=3, pady=(0, 0))
        
        clear_btn = ttk.Button(
            button_frame,
            text="清除结果",
            command=self.clear_results,
            width=15
        )
        clear_btn.grid(row=0, column=0, padx=5)
        
        export_txt_btn = ttk.Button(
            button_frame,
            text="导出文本",
            command=self.export_text_report,
            width=15
        )
        export_txt_btn.grid(row=0, column=1, padx=5)
        
        export_html_btn = ttk.Button(
            button_frame,
            text="导出HTML报告",
            command=self.export_html_report,
            width=15
        )
        export_html_btn.grid(row=0, column=2, padx=5)
        
        export_excel_btn = ttk.Button(
            button_frame,
            text="导出Excel",
            command=self.export_excel_report,
            width=15
        )
        export_excel_btn.grid(row=0, column=3, padx=5)
    
    def browse_folder(self):
        """浏览并选择文件夹"""
        folder_path = filedialog.askdirectory(
            title="选择 Git 仓库文件夹",
            initialdir=os.path.expanduser("~")
        )
        if folder_path:
            self.repo_path.set(folder_path)
            self.log_message(f"已选择路径: {folder_path}", "info")
            
            # 立即检测并显示该仓库的Git用户信息
            self.detect_git_user(folder_path)
            
            # 检测缓存
            self.check_cache()
    
    def detect_git_user(self, repo_path):
        """检测并显示Git仓库的用户信息（只读取本地配置）"""
        try:
            # 打开仓库
            repo = git.Repo(repo_path)
            
            # 只读取仓库本地配置，不读取全局配置
            git_user_name = None
            git_user_email = None
            
            try:
                # 只从本地配置读取
                with repo.config_reader() as config:
                    try:
                        git_user_name = config.get_value("user", "name", default=None)
                    except Exception:
                        git_user_name = None
                    
                    try:
                        git_user_email = config.get_value("user", "email", default=None)
                    except Exception:
                        git_user_email = None
            except Exception:
                pass
            
            # 显示用户信息（支持只有用户名或只有邮箱的情况）
            if git_user_name or git_user_email:
                if git_user_name and git_user_email:
                    display_text = f"{git_user_name} <{git_user_email}>"
                elif git_user_name:
                    display_text = f"{git_user_name}"
                else:
                    display_text = f"<{git_user_email}>"
                
                self.git_user_info.config(
                    text=f"✓ 检测到用户：{display_text} （本地配置）",
                    foreground="green"
                )
            else:
                self.git_user_info.config(
                    text="⚠ 未检测到本地Git配置，请执行: git config user.name \"your_name\"",
                    foreground="orange"
                )
        
        except git.exc.InvalidGitRepositoryError:
            self.git_user_info.config(
                text="✗ 所选路径不是有效的 Git 仓库",
                foreground="red"
            )
        except Exception as e:
            self.git_user_info.config(
                text=f"✗ 检测Git配置失败：{str(e)}",
                foreground="red"
            )
    
    def log_message(self, message, tag="info"):
        """在结果框中显示消息"""
        self.result_text.insert(tk.END, message + "\n", tag)
        self.result_text.see(tk.END)
        self.root.update()
    
    def clear_results(self):
        """清除结果"""
        self.result_text.delete(1.0, tk.END)
        self.status_label.config(text="请选择 Git 仓库文件夹", foreground="gray")
    
    def export_text_report(self):
        """导出文本报告到文件"""
        content = self.result_text.get(1.0, tk.END)
        if not content.strip():
            messagebox.showwarning("警告", "没有可导出的内容")
            return
        
        file_path = filedialog.asksaveasfilename(
            title="保存文本报告",
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(content)
                messagebox.showinfo("成功", f"文本报告已保存到:\n{file_path}")
            except Exception as e:
                messagebox.showerror("错误", f"保存失败:\n{str(e)}")
    
    def export_html_report(self):
        """导出 HTML 报告"""
        # 检查是否有统计数据
        if not self.current_repo_path or not self.current_user_name:
            messagebox.showwarning("警告", "请先执行统计分析")
            return
        
        # 选择保存路径
        file_path = filedialog.asksaveasfilename(
            title="保存 HTML 报告",
            defaultextension=".html",
            filetypes=[("HTML文件", "*.html"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                # 创建报告生成器
                generator = HTMLReportGenerator(
                    repo_path=self.current_repo_path,
                    user_name=self.current_user_name,
                    user_email=self.current_user_email,
                    branch=self.current_branch
                )
                
                # 生成报告（传递分账户数据）
                generator.generate(
                    self.stats, 
                    self.file_stats, 
                    file_path,
                    per_user_stats=self.per_user_stats if self.per_user_stats else None,
                    user_list=self.user_list if self.user_list else None
                )
                
                # 询问是否打开
                result = messagebox.askyesno(
                    "成功",
                    f"HTML 报告已保存到:\n{file_path}\n\n是否在浏览器中打开？"
                )
                
                if result:
                    import webbrowser
                    webbrowser.open('file://' + os.path.abspath(file_path))
                    
            except Exception as e:
                messagebox.showerror("错误", f"导出失败:\n{str(e)}")
                import traceback
                traceback.print_exc()
    
    def export_excel_report(self):
        """导出 Excel 报告"""
        # 检查是否有统计数据
        if not self.current_repo_path or not self.current_user_name:
            messagebox.showwarning("警告", "请先执行统计分析")
            return
        
        # 选择保存路径
        file_path = filedialog.asksaveasfilename(
            title="保存 Excel 报告",
            defaultextension=".xlsx",
            filetypes=[("Excel文件", "*.xlsx"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                # 创建导出器
                exporter = FileStatsExporter(
                    repo_path=self.current_repo_path,
                    user_name=self.current_user_name,
                    user_email=self.current_user_email,
                    branch=self.current_branch
                )
                
                # 导出（传递分账户数据）
                exporter.export_to_excel(
                    self.file_stats, 
                    self.stats, 
                    file_path,
                    per_user_stats=self.per_user_stats if self.per_user_stats else None,
                    user_list=self.user_list if self.user_list else None
                )
                
                # 询问是否打开
                result = messagebox.askyesno(
                    "成功",
                    f"Excel 报告已保存到:\n{file_path}\n\n是否打开文件？"
                )
                
                if result:
                    import os
                    os.startfile(file_path)
                    
            except Exception as e:
                messagebox.showerror("错误", f"导出失败:\n{str(e)}")
                import traceback
                traceback.print_exc()
    
    def start_analysis(self):
        """开始分析"""
        repo_path = self.repo_path.get().strip()
        
        if not repo_path:
            messagebox.showwarning("警告", "请先选择 Git 仓库文件夹")
            return
        
        if not os.path.exists(repo_path):
            messagebox.showerror("错误", "选择的路径不存在")
            return
        
        if self.is_analyzing:
            messagebox.showinfo("提示", "正在分析中，请稍候...")
            return
        
        # 清除之前的结果
        self.clear_results()
        
        # 重置统计数据
        self.stats = {
            'frontend': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
            'backend': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
            'other': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
        }
        self.file_stats = defaultdict(lambda: {'added': 0, 'deleted': 0, 'current': 0})
        self.current_stats_available = False
        self.per_user_stats = {}
        self.user_list = []
        
        # 在新线程中执行分析（避免界面冻结）
        thread = threading.Thread(target=self.run_analysis, args=(repo_path,))
        thread.daemon = True
        thread.start()
    
    def run_analysis(self, repo_path):
        """执行分析（在后台线程中）"""
        self.is_analyzing = True
        self.analyze_btn.config(state='disabled')
        self.progress.start()
        self.status_label.config(text="正在分析中...", foreground="blue")
        
        try:
            # 打开仓库
            try:
                repo = git.Repo(repo_path)
            except git.exc.InvalidGitRepositoryError:
                raise ValueError(f"'{repo_path}' 不是一个有效的 Git 仓库")
            except Exception as e:
                raise ValueError(f"无法打开 Git 仓库: {e}")
            
            # 先读取本地Git配置作为报告生成者信息
            local_git_user_name = None
            local_git_user_email = None
            try:
                with repo.config_reader() as config:
                    try:
                        local_git_user_name = config.get_value("user", "name", default=None)
                    except Exception:
                        pass
                    try:
                        local_git_user_email = config.get_value("user", "email", default=None)
                    except Exception:
                        pass
            except Exception:
                pass
            
            # 获取用户名和邮箱（优先使用手动输入，否则从本地配置读取）
            manual_names = [name.strip() for name in self.manual_user_name.get().split(',') if name.strip()]
            manual_emails = [email.strip() for email in self.manual_user_email.get().split(',') if email.strip()]
            
            git_user_names = []  # 支持多个用户名
            git_user_emails = []  # 支持多个邮箱
            user_source = ""
            
            if manual_names or manual_emails:
                # 使用手动输入的用户信息
                git_user_names = manual_names
                git_user_emails = manual_emails
                user_source = "（手动指定）"
                
                if not git_user_names and not git_user_emails:
                    raise ValueError("请至少输入一个用户名或邮箱")
            else:
                # 从本地配置读取
                try:
                    with repo.config_reader() as config:
                        try:
                            user_name = config.get_value("user", "name", default=None)
                            if user_name:
                                git_user_names = [user_name]
                        except Exception:
                            pass
                        
                        try:
                            user_email = config.get_value("user", "email", default=None)
                            if user_email:
                                git_user_emails = [user_email]
                        except Exception:
                            pass
                    
                    if not git_user_names and not git_user_emails:
                        raise ValueError("未检测到本地 Git 用户配置")
                    
                    user_source = "（本地配置）"
                except Exception as e:
                    raise ValueError(f"无法获取 Git 用户配置：{str(e)}\n请手动输入用户名或在仓库目录执行: git config user.name \"your_name\"")
            
            # 保存信息用于导出（报告生成者使用本地Git配置）
            self.current_repo_path = repo_path
            self.current_user_name = local_git_user_name  # 使用本地Git配置作为报告生成者
            self.current_user_email = local_git_user_email  # 使用本地Git配置
            self.current_branch = repo.active_branch.name
            
            # 格式化用户显示信息
            user_display_list = []
            if git_user_names:
                user_display_list.extend(git_user_names)
            if git_user_emails:
                user_display_list.extend([f"<{email}>" for email in git_user_emails])
            
            user_display = ", ".join(user_display_list)
            user_count = len(git_user_names) + len(git_user_emails)
            
            if user_count > 1:
                user_display += f" (共{user_count}个账户)"
            
            # 更新 GUI 显示当前 Git 用户
            self.git_user_info.config(
                text=f"✓ 当前统计用户：{user_display} {user_source}",
                foreground="green"
            )
            
            # 显示基本信息
            self.log_message("=" * 70, "separator")
            self.log_message("代码统计报告", "title")
            self.log_message("=" * 70, "separator")
            self.log_message(f"\n📊 统计说明：统计指定用户的提交", "warning")
            self.log_message(f"👤 统计用户: {user_display} {user_source}", "info")
            self.log_message(f"📁 仓库路径: {repo_path}", "info")
            self.log_message(f"🌿 当前分支: {repo.active_branch.name}", "info")
            self.log_message(f"📌 统计方法: 基于 Git diff，只统计您的提交变更\n", "warning")
            
            # 保存用户列表
            self.user_list = git_user_names + [f"<{email}>" for email in git_user_emails]
            
            # 获取所有提交
            commits = list(repo.iter_commits(repo.active_branch.name))
            total_commits = len(commits)
            
            self.log_message(f"共有 {total_commits} 个提交，正在分析...\n", "warning")
            
            # 根据统计模式执行不同的分析
            stat_mode = self.stat_mode.get()
            
            if stat_mode == "detailed" and user_count > 1:
                # 分账户统计模式
                self.log_message(f"📊 统计模式：分账户统计（共{user_count}个账户）\n", "warning")
                self.analyze_detailed_mode(repo, git_user_names, git_user_emails, commits)
            else:
                # 汇总统计模式
                self.log_message(f"📊 统计模式：汇总统计\n", "warning")
                
                # 分析每个提交
                for i, commit in enumerate(commits, 1):
                    if i % 10 == 0 or i == total_commits:
                        self.status_label.config(
                            text=f"正在分析: {i}/{total_commits}",
                            foreground="blue"
                        )
                    
                    self.analyze_commit(commit, git_user_names, git_user_emails)
                
                self.log_message("\n✓ 历史变更分析完成！", "success")
                
                # 分析当前代码量
                self.log_message("\n正在分析当前代码量（使用 git blame）...", "warning")
                self.status_label.config(text="正在分析当前代码量...", foreground="blue")
                self.analyze_current_code(repo, git_user_names, git_user_emails)
            
            # 显示结果
            self.display_results()
            
            # 保存缓存
            self.save_to_cache(repo, git_user_names, git_user_emails)
            
            self.status_label.config(text="分析完成！", foreground="green")
            self.log_message("\n✓ 分析完成！", "success")
            
            # 重新检查缓存状态
            self.check_cache()
            
        except ValueError as e:
            self.log_message(f"\n✗ 错误: {str(e)}", "error")
            self.status_label.config(text="分析失败", foreground="red")
            messagebox.showerror("错误", str(e))
        except Exception as e:
            self.log_message(f"\n✗ 发生错误: {str(e)}", "error")
            self.status_label.config(text="分析失败", foreground="red")
            messagebox.showerror("错误", f"发生错误:\n{str(e)}")
        finally:
            self.is_analyzing = False
            self.analyze_btn.config(state='normal')
            self.progress.stop()
    
    def is_comment_line(self, line: str, file_ext: str, in_multi_comment: bool) -> Tuple[bool, bool]:
        """判断是否为注释行"""
        stripped = line.strip()
        
        if not stripped:
            return False, in_multi_comment
        
        # 检查多行注释
        if file_ext in self.MULTI_LINE_COMMENT:
            start_pattern, end_pattern = self.MULTI_LINE_COMMENT[file_ext]
            
            if re.match(start_pattern, stripped):
                in_multi_comment = True
                if re.search(end_pattern, stripped):
                    in_multi_comment = False
                return True, in_multi_comment
            
            if in_multi_comment:
                if re.search(end_pattern, stripped):
                    in_multi_comment = False
                return True, in_multi_comment
        
        if in_multi_comment:
            return True, in_multi_comment
        
        # 检查单行注释
        if file_ext in self.SINGLE_LINE_COMMENT:
            pattern = self.SINGLE_LINE_COMMENT[file_ext]
            if re.match(pattern, stripped):
                return True, in_multi_comment
        
        return False, in_multi_comment
    
    def classify_file(self, file_path: str) -> str:
        """分类文件类型"""
        _, ext = os.path.splitext(file_path.lower())
        
        if ext in self.FRONTEND_EXTENSIONS:
            return 'frontend'
        elif ext in self.BACKEND_EXTENSIONS:
            return 'backend'
        else:
            return 'other'
    
    def count_diff_lines(self, diff_text: str, file_ext: str) -> Tuple[int, int]:
        """统计 diff 中的新增和删除行数"""
        added = 0
        deleted = 0
        in_multi_comment = False
        
        for line in diff_text.split('\n'):
            if not line:
                continue
            
            if line.startswith('@@') or line.startswith('diff --git') or \
               line.startswith('index ') or line.startswith('---') or \
               line.startswith('+++'):
                continue
            
            if line.startswith('+'):
                code_line = line[1:]
                is_comment, in_multi_comment = self.is_comment_line(code_line, file_ext, in_multi_comment)
                if not is_comment and code_line.strip():
                    added += 1
            
            elif line.startswith('-'):
                code_line = line[1:]
                is_comment, in_multi_comment = self.is_comment_line(code_line, file_ext, in_multi_comment)
                if not is_comment and code_line.strip():
                    deleted += 1
        
        return added, deleted
    
    def analyze_detailed_mode(self, repo, git_user_names, git_user_emails, commits):
        """分账户统计模式"""
        total_commits = len(commits)
        all_users = git_user_names + git_user_emails
        
        for idx, user in enumerate(all_users, 1):
            is_email = user in git_user_emails
            user_display = f"<{user}>" if is_email else user
            
            self.log_message(f"\n{'='*70}", "separator")
            self.log_message(f"正在分析账户 {idx}/{len(all_users)}: {user_display}", "title")
            self.log_message(f"{'='*70}\n", "separator")
            
            # 初始化该用户的统计
            user_stats = {
                'frontend': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
                'backend': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
                'other': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
            }
            user_file_stats = defaultdict(lambda: {'added': 0, 'deleted': 0, 'current': 0})
            
            # 分析提交
            for i, commit in enumerate(commits, 1):
                if i % 10 == 0 or i == total_commits:
                    self.status_label.config(
                        text=f"账户{idx}/{len(all_users)}: {i}/{total_commits}",
                        foreground="blue"
                    )
                
                # 检查是否匹配当前用户
                is_match = False
                if not is_email and commit.author.name == user:
                    is_match = True
                elif is_email and commit.author.email == user:
                    is_match = True
                
                if is_match:
                    self.analyze_commit_for_user(commit, user_stats, user_file_stats)
            
            self.log_message(f"✓ 历史变更分析完成", "success")
            
            # 分析当前代码量
            self.log_message(f"正在分析当前代码量...", "warning")
            self.analyze_current_code_for_user(repo, [user] if not is_email else [], [user] if is_email else [], user_stats, user_file_stats)
            
            self.log_message(f"✓ 当前代码量分析完成", "success")
            
            # 保存该用户的统计
            self.per_user_stats[user_display] = {
                'stats': user_stats,
                'file_stats': dict(user_file_stats)
            }
            
            # 累加到总统计
            for key in ['frontend', 'backend', 'other']:
                for metric in ['added', 'deleted', 'total', 'current']:
                    self.stats[key][metric] += user_stats[key][metric]
            
            for file_path, stats in user_file_stats.items():
                self.file_stats[file_path]['added'] += stats['added']
                self.file_stats[file_path]['deleted'] += stats['deleted']
                self.file_stats[file_path]['current'] += stats['current']
        
        self.current_stats_available = True
        self.log_message(f"\n{'='*70}", "separator")
        self.log_message(f"✓ 所有账户分析完成！", "success")
        self.log_message(f"{'='*70}\n", "separator")
    
    def analyze_commit_for_user(self, commit, user_stats, user_file_stats):
        """为特定用户分析单个提交"""
        # 跳过合并提交（Merge Commit）
        if len(commit.parents) > 1:
            return
        
        if not commit.parents:
            parent = None
        else:
            parent = commit.parents[0]
        
        try:
            if parent:
                diffs = parent.diff(commit, create_patch=True)
            else:
                diffs = commit.diff(git.NULL_TREE, create_patch=True)
        except Exception:
            return
        
        for diff_item in diffs:
            file_path = diff_item.b_path if diff_item.b_path else diff_item.a_path
            if not file_path:
                continue
            
            # 判断文件变更类型
            is_new_file = diff_item.new_file
            is_deleted_file = diff_item.deleted_file
            is_renamed_file = diff_item.renamed_file
            
            file_type = self.classify_file(file_path)
            _, file_ext = os.path.splitext(file_path.lower())
            
            try:
                if diff_item.diff:
                    diff_text = diff_item.diff.decode('utf-8', errors='ignore')
                else:
                    continue
            except Exception:
                continue
            
            added, deleted = self.count_diff_lines(diff_text, file_ext)
            
            # 计算工作量（智能算法）
            if is_new_file:
                # 新建文件：净增量
                workload = added - deleted
            elif is_deleted_file:
                # 删除文件：不算工作量
                workload = 0
            elif is_renamed_file:
                # 重命名文件：按新建处理
                workload = added - deleted
            else:
                # 修改文件：新增×0.9 + 删除×0.1
                workload = int(added * 0.9 + deleted * 0.1)
            
            user_stats[file_type]['added'] += added
            user_stats[file_type]['deleted'] += deleted
            user_stats[file_type]['total'] += workload
            
            user_file_stats[file_path]['added'] += added
            user_file_stats[file_path]['deleted'] += deleted
    
    def analyze_current_code_for_user(self, repo, git_user_names, git_user_emails, user_stats, user_file_stats):
        """为特定用户分析当前代码量"""
        try:
            git_cmd = repo.git
            try:
                files_output = git_cmd.execute(['git', 'ls-files'])
                tracked_files = [f.strip() for f in files_output.split('\n') if f.strip()]
            except Exception:
                return
            
            for file_path in tracked_files:
                _, file_ext = os.path.splitext(file_path.lower())
                file_type = self.classify_file(file_path)
                
                full_path = os.path.join(self.current_repo_path, file_path)
                if not os.path.exists(full_path):
                    continue
                
                try:
                    blame_output = git_cmd.blame('-e', '--line-porcelain', file_path)
                    user_lines = 0
                    in_multi_comment = False
                    
                    lines = blame_output.split('\n')
                    i = 0
                    while i < len(lines):
                        line = lines[i]
                        
                        if line and not line.startswith('\t'):
                            author_name = None
                            author_mail = None
                            j = i
                            while j < len(lines) and not lines[j].startswith('\t'):
                                if lines[j].startswith('author '):
                                    author_name = lines[j][7:].strip()
                                elif lines[j].startswith('author-mail '):
                                    author_mail = lines[j][12:].strip()
                                j += 1
                            
                            while j < len(lines) and not lines[j].startswith('\t'):
                                j += 1
                            
                            if j < len(lines):
                                code_line = lines[j][1:]
                                
                                is_current_user = False
                                if author_name and git_user_names and author_name in git_user_names:
                                    is_current_user = True
                                if not is_current_user and author_mail and git_user_emails:
                                    for email in git_user_emails:
                                        if f'<{email}>' in author_mail or email in author_mail:
                                            is_current_user = True
                                            break
                                
                                if is_current_user:
                                    is_comment, in_multi_comment = self.is_comment_line(
                                        code_line, file_ext, in_multi_comment
                                    )
                                    if not is_comment and code_line.strip():
                                        user_lines += 1
                            
                            i = j + 1
                        else:
                            i += 1
                    
                    if user_lines > 0:
                        user_stats[file_type]['current'] += user_lines
                        user_file_stats[file_path]['current'] = user_lines
                
                except Exception:
                    continue
        except Exception:
            pass
    
    def analyze_commit(self, commit, git_user_names, git_user_emails):
        """分析单个提交（支持多个用户名和邮箱）"""
        # 跳过合并提交（Merge Commit）
        if len(commit.parents) > 1:
            return
        
        # 检查提交作者是否在指定的用户列表中
        is_match = False
        
        # 检查用户名匹配
        if git_user_names and commit.author.name in git_user_names:
            is_match = True
        
        # 检查邮箱匹配
        if not is_match and git_user_emails and commit.author.email in git_user_emails:
            is_match = True
        
        if not is_match:
            return
        
        if not commit.parents:
            parent = None
        else:
            parent = commit.parents[0]
        
        try:
            if parent:
                diffs = parent.diff(commit, create_patch=True)
            else:
                diffs = commit.diff(git.NULL_TREE, create_patch=True)
        except Exception:
            return
        
        for diff_item in diffs:
            file_path = diff_item.b_path if diff_item.b_path else diff_item.a_path
            if not file_path:
                continue
            
            # 判断文件变更类型
            is_new_file = diff_item.new_file
            is_deleted_file = diff_item.deleted_file
            is_renamed_file = diff_item.renamed_file
            
            file_type = self.classify_file(file_path)
            _, file_ext = os.path.splitext(file_path.lower())
            
            try:
                if diff_item.diff:
                    diff_text = diff_item.diff.decode('utf-8', errors='ignore')
                else:
                    continue
            except Exception:
                continue
            
            added, deleted = self.count_diff_lines(diff_text, file_ext)
            
            # 计算工作量（智能算法）
            if is_new_file:
                # 新建文件：净增量
                workload = added - deleted
            elif is_deleted_file:
                # 删除文件：不算工作量
                workload = 0
            elif is_renamed_file:
                # 重命名文件：按新建处理
                workload = added - deleted
            else:
                # 修改文件：新增×0.9 + 删除×0.1
                workload = int(added * 0.9 + deleted * 0.1)
            
            self.stats[file_type]['added'] += added
            self.stats[file_type]['deleted'] += deleted
            self.stats[file_type]['total'] += workload
            
            self.file_stats[file_path]['added'] += added
            self.file_stats[file_path]['deleted'] += deleted
    
    def analyze_current_code(self, repo, git_user_names, git_user_emails):
        """
        分析当前代码量（基于 git blame）
        统计当前工作区中属于指定用户的代码行数
        支持多个用户名和邮箱
        """
        try:
            # 获取所有被 Git 跟踪的文件
            git_cmd = repo.git
            try:
                files_output = git_cmd.execute(['git', 'ls-files'])
                tracked_files = [f.strip() for f in files_output.split('\n') if f.strip()]
            except Exception as e:
                self.log_message(f"获取文件列表失败：{e}", "error")
                return
            
            if not tracked_files:
                self.log_message("没有找到被跟踪的文件", "warning")
                return
            
            total_files = len(tracked_files)
            self.log_message(f"共找到 {total_files} 个文件，正在分析...", "warning")
            
            processed = 0
            for file_path in tracked_files:
                processed += 1
                if processed % 10 == 0 or processed == total_files:
                    self.status_label.config(
                        text=f"分析当前代码: {processed}/{total_files} ({processed*100//total_files}%)",
                        foreground="blue"
                    )
                
                # 获取文件扩展名和类型
                _, file_ext = os.path.splitext(file_path.lower())
                file_type = self.classify_file(file_path)
                
                # 获取文件的完整路径
                full_path = os.path.join(self.current_repo_path, file_path)
                
                # 检查文件是否存在
                if not os.path.exists(full_path):
                    continue
                
                # 使用 git blame 分析文件
                try:
                    # 执行 git blame
                    blame_output = git_cmd.blame('-e', '--line-porcelain', file_path)
                    
                    # 解析 blame 输出，统计当前用户的代码行
                    user_lines = 0
                    in_multi_comment = False
                    
                    lines = blame_output.split('\n')
                    i = 0
                    while i < len(lines):
                        line = lines[i]
                        
                        # blame 输出格式：每个代码块以 commit hash 开始
                        if line and not line.startswith('\t'):
                            # 查找 author 和 author-mail 行
                            author_name = None
                            author_mail = None
                            j = i
                            while j < len(lines) and not lines[j].startswith('\t'):
                                if lines[j].startswith('author '):
                                    author_name = lines[j][7:].strip()
                                elif lines[j].startswith('author-mail '):
                                    author_mail = lines[j][12:].strip()
                                j += 1
                            
                            # 查找实际的代码行（以 \t 开头）
                            while j < len(lines) and not lines[j].startswith('\t'):
                                j += 1
                            
                            if j < len(lines):
                                code_line = lines[j][1:]  # 去掉开头的 \t
                                
                                # 匹配指定的用户（支持多个用户名和邮箱）
                                is_current_user = False
                                
                                # 检查用户名匹配
                                if author_name and git_user_names and author_name in git_user_names:
                                    is_current_user = True
                                
                                # 检查邮箱匹配
                                if not is_current_user and author_mail and git_user_emails:
                                    for email in git_user_emails:
                                        if f'<{email}>' in author_mail or email in author_mail:
                                            is_current_user = True
                                            break
                                
                                if is_current_user:
                                    # 检查是否是注释或空行
                                    is_comment, in_multi_comment = self.is_comment_line(
                                        code_line, file_ext, in_multi_comment
                                    )
                                    
                                    if not is_comment and code_line.strip():
                                        user_lines += 1
                            
                            i = j + 1
                        else:
                            i += 1
                    
                    # 更新统计
                    if user_lines > 0:
                        self.stats[file_type]['current'] += user_lines
                        self.file_stats[file_path]['current'] = user_lines
                
                except Exception:
                    # 某些文件可能无法 blame（如二进制文件）
                    continue
            
            self.log_message(f"✓ 当前代码量分析完成！", "success")
            self.current_stats_available = True
            
        except Exception as e:
            self.log_message(f"当前代码量分析失败：{e}", "error")
    
    def display_results(self):
        """显示统计结果"""
        frontend = self.stats['frontend']
        backend = self.stats['backend']
        other = self.stats['other']
        
        # 说明文字
        self.log_message("\n" + "=" * 70, "separator")
        self.log_message("统计说明", "header")
        self.log_message("=" * 70, "separator")
        self.log_message("  📊 累计工作量：统计所有历史提交的代码变更（包括后来修改/删除的）", "warning")
        if self.current_stats_available:
            self.log_message("  📝 当前代码量：统计当前代码库中属于你的有效代码行数", "warning")
        
        # 前端统计
        self.log_message("\n" + "=" * 70, "separator")
        self.log_message("前端代码统计", "header")
        self.log_message("=" * 70, "separator")
        self.log_message("  【累计工作量】", "warning")
        self.log_message(f"    新增行数: {frontend['added']:>10,}", "success")
        self.log_message(f"    删除行数: {frontend['deleted']:>10,}", "error")
        self.log_message(f"    净增行数: {frontend['total']:>10,}", "info")
        if self.current_stats_available:
            self.log_message("  【当前代码量】", "warning")
            self.log_message(f"    当前拥有: {frontend['current']:>10,} 行", "title")
        
        # 后端统计
        self.log_message("\n" + "=" * 70, "separator")
        self.log_message("后端代码统计", "header")
        self.log_message("=" * 70, "separator")
        self.log_message("  【累计工作量】", "warning")
        self.log_message(f"    新增行数: {backend['added']:>10,}", "success")
        self.log_message(f"    删除行数: {backend['deleted']:>10,}", "error")
        self.log_message(f"    净增行数: {backend['total']:>10,}", "info")
        if self.current_stats_available:
            self.log_message("  【当前代码量】", "warning")
            self.log_message(f"    当前拥有: {backend['current']:>10,} 行", "title")
        
        # 其他文件
        if other['added'] > 0 or other['deleted'] > 0 or (self.current_stats_available and other['current'] > 0):
            self.log_message("\n" + "=" * 70, "separator")
            self.log_message("其他文件统计", "header")
            self.log_message("=" * 70, "separator")
            self.log_message("  【累计工作量】", "warning")
            self.log_message(f"    新增行数: {other['added']:>10,}", "success")
            self.log_message(f"    删除行数: {other['deleted']:>10,}", "error")
            self.log_message(f"    净增行数: {other['total']:>10,}", "info")
            if self.current_stats_available:
                self.log_message("  【当前代码量】", "warning")
                self.log_message(f"    当前拥有: {other['current']:>10,} 行", "title")
        
        # 总计
        total_added = frontend['added'] + backend['added'] + other['added']
        total_deleted = frontend['deleted'] + backend['deleted'] + other['deleted']
        total_net = frontend['total'] + backend['total'] + other['total']
        total_current = frontend['current'] + backend['current'] + other['current']
        
        self.log_message("\n" + "=" * 70, "separator")
        self.log_message("总计", "title")
        self.log_message("=" * 70, "separator")
        self.log_message("  【累计工作量】", "warning")
        self.log_message(f"    新增行数: {total_added:>10,}", "success")
        self.log_message(f"    删除行数: {total_deleted:>10,}", "error")
        self.log_message(f"    净增行数: {total_net:>10,}", "info")
        if self.current_stats_available:
            self.log_message("  【当前代码量】", "warning")
            self.log_message(f"    当前拥有: {total_current:>10,} 行", "title")
        
        # 数据对比
        if self.current_stats_available and total_added > 0:
            work_ratio = (total_added / total_current * 100) if total_current > 0 else 0
            self.log_message("\n" + "=" * 70, "separator")
            self.log_message("数据对比", "header")
            self.log_message("=" * 70, "separator")
            self.log_message(f"  💡 你累计写了 {total_added:,} 行代码", "info")
            self.log_message(f"  💡 当前代码库中有 {total_current:,} 行是你的", "info")
            if total_current > 0:
                self.log_message(f"  💡 工作效率比：{work_ratio:.1f}% （累计÷当前）", "info")
                if work_ratio > 150:
                    self.log_message("     → 说明：代码经历了较多的重构和优化（这是好事！）", "warning")
                elif work_ratio > 110:
                    self.log_message("     → 说明：代码质量稳定，适度重构", "success")
                else:
                    self.log_message("     → 说明：代码一次成型，修改较少", "info")
        
        # 显示文件排行
        if self.file_stats:
            self.log_message("\n" + "=" * 70, "separator")
            self.log_message("修改最多的 10 个文件", "header")
            self.log_message("=" * 70, "separator")
            
            sorted_files = sorted(
                self.file_stats.items(),
                key=lambda x: x[1]['added'] - x[1]['deleted'],
                reverse=True
            )[:10]
            
            for i, (file_path, stats) in enumerate(sorted_files, 1):
                net_change = stats['added'] - stats['deleted']
                self.log_message(f"{i:2}. {file_path}", "info")
                if self.current_stats_available:
                    self.log_message(
                        f"    累计 - 新增: {stats['added']:>6}  删除: {stats['deleted']:>6}  净增: {net_change:>6}",
                        "info"
                    )
                    self.log_message(
                        f"    当前 - 拥有: {stats.get('current', 0):>6} 行",
                        "title"
                    )
                else:
                    self.log_message(
                        f"    新增: {stats['added']:>6}  删除: {stats['deleted']:>6}  净增: {net_change:>6}",
                        "info"
                    )
    
    def check_cache(self):
        """检测并显示缓存状态"""
        repo_path = self.repo_path.get().strip()
        if not repo_path:
            return
        
        try:
            # 打开仓库
            self.current_repo = git.Repo(repo_path)
            
            # 获取当前配置
            manual_names = [name.strip() for name in self.manual_user_name.get().split(',') if name.strip()]
            manual_emails = [email.strip() for email in self.manual_user_email.get().split(',') if email.strip()]
            
            # 确定用户列表
            users = []
            if manual_names or manual_emails:
                users = manual_names + manual_emails
            else:
                # 从本地配置读取
                try:
                    with self.current_repo.config_reader() as config:
                        try:
                            user_name = config.get_value("user", "name", default=None)
                            if user_name:
                                users.append(user_name)
                        except:
                            pass
                        try:
                            user_email = config.get_value("user", "email", default=None)
                            if user_email:
                                users.append(user_email)
                        except:
                            pass
                except:
                    pass
            
            if not users:
                self.show_no_cache()
                return
            
            # 获取当前分支和统计模式
            branch = self.current_repo.active_branch.name
            stat_mode = self.stat_mode.get()
            
            # 尝试加载缓存
            print(f"\n[缓存调试]")
            print(f"仓库路径: {repo_path}")
            print(f"用户列表: {users}")
            print(f"分支: {branch}")
            print(f"统计模式: {stat_mode}")
            
            cache_data = self.cache_manager.load_cache(repo_path, users, branch, stat_mode)
            
            if not cache_data:
                print(f"❌ 未找到缓存文件")
                self.show_no_cache()
                return
            
            print(f"✓ 找到缓存文件")
            print(f"缓存元数据:")
            print(f"  - 仓库路径: {cache_data.get('metadata', {}).get('repo_path')}")
            print(f"  - 用户列表: {cache_data.get('metadata', {}).get('users')}")
            print(f"  - 分支: {cache_data.get('metadata', {}).get('branch')}")
            print(f"  - 统计模式: {cache_data.get('metadata', {}).get('stat_mode')}")
            
            # 验证缓存
            is_valid, reason = self.cache_manager.validate_cache(
                cache_data, self.current_repo, users, branch, stat_mode
            )
            
            print(f"验证结果: {'✓ 有效' if is_valid else '✗ 无效'}")
            if not is_valid:
                print(f"原因: {reason}")
            
            if is_valid:
                self.show_cache_available(cache_data)
            else:
                self.show_cache_outdated(cache_data, reason)
                
        except git.exc.InvalidGitRepositoryError:
            self.cache_status_label.config(
                text="✗ 所选路径不是有效的 Git 仓库",
                foreground="red"
            )
            self.hide_cache_buttons()
        except Exception as e:
            self.cache_status_label.config(
                text=f"✗ 检查缓存失败: {str(e)}",
                foreground="red"
            )
            self.hide_cache_buttons()
    
    def show_no_cache(self):
        """显示无缓存状态"""
        cache_count = self.cache_manager.get_cache_count()
        cache_size = self.cache_manager.get_cache_size()
        
        self.cache_status_label.config(
            text=f"✗ 无可用缓存  |  已有 {cache_count} 个缓存文件 ({cache_size})",
            foreground="gray"
        )
        self.current_cache = None
        self.hide_cache_buttons()
        
        # 只显示清理缓存按钮
        if cache_count > 0:
            self.clear_cache_btn.pack(side=tk.LEFT, padx=(0, 5))
    
    def show_cache_available(self, cache_data):
        """显示有效缓存"""
        info = self.cache_manager.get_cache_info(cache_data)
        
        self.cache_status_label.config(
            text=f"✓ 找到有效缓存  |  生成时间: {info['create_time']}  |  提交: {info['last_commit_id']}",
            foreground="green"
        )
        self.current_cache = cache_data
        
        # 显示加载缓存和重新统计按钮
        self.hide_cache_buttons()
        self.load_cache_btn.pack(side=tk.LEFT, padx=(0, 5))
        self.restat_btn.pack(side=tk.LEFT, padx=(0, 5))
        self.clear_cache_btn.pack(side=tk.LEFT, padx=(0, 5))
    
    def show_cache_outdated(self, cache_data, reason):
        """显示过期缓存"""
        info = self.cache_manager.get_cache_info(cache_data)
        
        self.cache_status_label.config(
            text=f"⚠ 缓存过期 ({reason})  |  上次统计: {info['create_time']}",
            foreground="orange"
        )
        self.current_cache = cache_data
        
        # 显示加载旧缓存和重新统计按钮
        self.hide_cache_buttons()
        self.load_cache_btn.config(text="📂 加载旧缓存")
        self.load_cache_btn.pack(side=tk.LEFT, padx=(0, 5))
        self.restat_btn.pack(side=tk.LEFT, padx=(0, 5))
        self.clear_cache_btn.pack(side=tk.LEFT, padx=(0, 5))
    
    def hide_cache_buttons(self):
        """隐藏所有缓存按钮"""
        self.load_cache_btn.pack_forget()
        self.restat_btn.pack_forget()
        self.clear_cache_btn.pack_forget()
    
    def load_from_cache(self):
        """从缓存加载统计结果"""
        if not self.current_cache:
            messagebox.showwarning("警告", "没有可用的缓存")
            return
        
        try:
            # 加载缓存数据
            self.stats = self.current_cache['stats']
            self.file_stats = defaultdict(lambda: {'added': 0, 'deleted': 0, 'current': 0})
            for file_path, stats in self.current_cache['file_stats'].items():
                self.file_stats[file_path] = stats
            
            self.per_user_stats = self.current_cache.get('per_user_stats', {})
            self.user_list = self.current_cache.get('user_list', [])
            
            # 检查是否有当前代码量数据
            total_current = sum(
                self.stats[key].get('current', 0) 
                for key in ['frontend', 'backend', 'other']
            )
            self.current_stats_available = total_current > 0
            
            # 设置仓库信息
            metadata = self.current_cache['metadata']
            self.current_repo_path = metadata['repo_path']
            self.current_branch = metadata['branch']
            
            # 从本地Git配置读取报告生成者信息
            try:
                repo = git.Repo(self.current_repo_path)
                with repo.config_reader() as config:
                    try:
                        self.current_user_name = config.get_value("user", "name", default=None)
                    except:
                        self.current_user_name = None
                    try:
                        self.current_user_email = config.get_value("user", "email", default=None)
                    except:
                        self.current_user_email = None
            except:
                self.current_user_name = None
                self.current_user_email = None
            
            # 显示结果
            self.display_results()
            
            self.status_label.config(text="✓ 已从缓存加载统计结果", foreground="green")
            self.log_message("\n✓ 已从缓存加载统计结果！", "success")
            
            messagebox.showinfo("成功", "已从缓存加载统计结果！\n\n💡 提示：如果有新提交，建议重新统计")
            
        except Exception as e:
            messagebox.showerror("错误", f"加载缓存失败:\n{str(e)}")
            import traceback
            traceback.print_exc()
    
    def save_to_cache(self, repo, git_user_names, git_user_emails):
        """保存统计结果到缓存"""
        try:
            repo_path = str(repo.working_dir)
            users = git_user_names + git_user_emails
            branch = repo.active_branch.name
            stat_mode = self.stat_mode.get()
            
            # 获取最后一次提交信息
            last_commit = repo.head.commit
            last_commit_id = last_commit.hexsha
            last_commit_time = datetime.datetime.fromtimestamp(last_commit.committed_date).strftime('%Y-%m-%d %H:%M:%S')
            
            # 获取总提交数
            total_commits = len(list(repo.iter_commits(branch)))
            
            # 保存缓存
            cache_file = self.cache_manager.save_cache(
                repo_path=repo_path,
                users=users,
                branch=branch,
                stat_mode=stat_mode,
                last_commit_id=last_commit_id,
                last_commit_time=last_commit_time,
                total_commits=total_commits,
                stats=self.stats,
                file_stats=self.file_stats,
                per_user_stats=self.per_user_stats if self.per_user_stats else None,
                user_list=self.user_list if self.user_list else None
            )
            
            self.log_message(f"\n💾 已保存缓存: {os.path.basename(cache_file)}", "success")
            
        except Exception as e:
            self.log_message(f"\n⚠ 保存缓存失败: {str(e)}", "warning")
    
    def clear_all_caches(self):
        """清理所有缓存"""
        result = messagebox.askyesno(
            "确认清理",
            "确定要清理所有缓存文件吗？\n\n清理后需要重新统计。"
        )
        
        if result:
            try:
                count = self.cache_manager.clear_all_caches()
                messagebox.showinfo("成功", f"已清理 {count} 个缓存文件")
                self.check_cache()  # 重新检查缓存状态
            except Exception as e:
                messagebox.showerror("错误", f"清理缓存失败:\n{str(e)}")


def main():
    """主函数"""
    root = tk.Tk()
    app = GitCounterGUI(root)
    root.mainloop()


if __name__ == '__main__':
    main()

